import sys
import requests
import time
import json
import logging
import psutil

# 日志配置
logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s')
logger = logging.getLogger(__name__)

# 配置文件路径
CONFIG_FILE = "../config/reboot_config.json"
DINGTALK_CONFIG_FILE = "../config/dingtalk_config.json"


# ==================== 工具函数 ====================

# 从配置文件加载配置
def load_config():
	try:
		with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
			config = json.load(f)
			required_fields = ["pc_name", "push_group", "heartbeat_interval", "enabled"]
			for field in required_fields:
				if field not in config:
					logger.error(f"配置文件缺少必要字段: {field}")
					sys.exit(1)
			return config
	except FileNotFoundError:
		logger.error(f"配置文件未找到: {CONFIG_FILE}")
		sys.exit(1)
	except json.JSONDecodeError:
		logger.error(f"配置文件格式错误: {CONFIG_FILE}")
		sys.exit(1)


# 从钉钉配置中根据 group_name 获取 webhook 配置
def get_dingtalk_webhook(group_name):
	try:
		with open(DINGTALK_CONFIG_FILE, 'r', encoding='utf-8') as f:
			dingtalk_configs = json.load(f)
			for config in dingtalk_configs:
				if config.get("group_name") == group_name:
					return {
						"group_name": config["group_name"],
						"webhook": config["webhook"],
						"secret": config.get("secret", ""),
						"at_mobiles": config.get("at_mobiles", [])
					}
			logger.warning(f"找不到钉钉群组: {group_name}")
			return None
	except FileNotFoundError:
		logger.warning(f"钉钉配置文件未找到: {DINGTALK_CONFIG_FILE}")
		return None
	except json.JSONDecodeError:
		logger.warning(f"钉钉配置文件格式错误: {DINGTALK_CONFIG_FILE}")
		return None


# 获取第一个活动网卡的MAC地址
def get_mac_address():
	""" 获取第一个活动网卡的MAC地址 """
	for interface, addrs in psutil.net_if_addrs().items():
		for addr in addrs:
			if addr.family == psutil.AF_LINK:
				return addr.address.replace("-", ":").lower()  # 统一格式为 xx:xx:xx:xx:xx:xx
	logger.error("无法找到有效的网卡MAC地址")
	return None


# 获取系统开机时间（秒）
def get_system_uptime():
	boot_time = psutil.boot_time()
	current_time = time.time()
	return int(current_time - boot_time)


# 获取当前时间戳（模拟 NTP 时间）
def get_current_time():
	return int(time.time())


# 发送心跳或注册包
def send_packet(packet_type, config, dingtalk_webhook):
	mac_address = get_mac_address()
	if not mac_address:
		logger.error("无法获取MAC地址，退出")
		sys.exit(1)
	
	current_time = get_current_time()
	pc_name = config["pc_name"]
	interval = config["heartbeat_interval"]
	enabled = config["enabled"]
	
	payload = {
		"type": packet_type,
		mac_address: {
			"name": pc_name,
			"uptime": get_system_uptime(),  # 使用系统运行时间（秒）
			"next_heartbeat": current_time + interval,  # 下次心跳时间
			"current_time": current_time,
			"enabled": enabled
		}
	}
	
	# 添加钉钉配置（可选）
	if dingtalk_webhook:
		payload[mac_address]["dingtalk"] = dingtalk_webhook
	
	logger.debug(f"发送 {packet_type} 请求: {json.dumps(payload, indent=2)}")
	
	try:
		SERVER_URL = "http://xrsdev.easysvn.cn:5556/heartbeat"  # 可以也从配置读取
		response = requests.post(SERVER_URL, json=payload, timeout=5)
		if response.status_code == 200:
			logger.info(f"{packet_type.capitalize()} 成功发送到服务器")
		else:
			logger.error(f"{packet_type.capitalize()} 失败，状态码: {response.status_code}，响应: {response.text}")
	except requests.exceptions.Timeout:
		logger.error("请求超时，请检查网络或服务端是否可用")
	except Exception as e:
		logger.error(f"发送 {packet_type} 请求时发生错误: {e}")


# ==================== 主程序 ====================
if __name__ == '__main__':
	# 加载配置
	config = load_config()
	if not config["enabled"]:
		logger.info("设备未启用，程序退出")
		sys.exit(0)
	
	# 获取钉钉配置
	dingtalk_webhook = get_dingtalk_webhook(config["push_group"])
	
	# 打印设备信息
	mac_address = get_mac_address()
	if not mac_address:
		sys.exit(1)
	
	logger.info(f"设备 MAC 地址: {mac_address}")
	logger.info(f"设备名称: {config['pc_name']}")
	logger.info(f"系统运行时间（秒）: {get_system_uptime()}")
	logger.info(f"心跳间隔: {config['heartbeat_interval']} 秒")
	
	# 注册设备
	send_packet("register", config, dingtalk_webhook)
	
	# 循环发送心跳
	while True:
		try:
			send_packet("heartbeat", config, dingtalk_webhook)
			time.sleep(config["heartbeat_interval"]//2)
		except KeyboardInterrupt:
			logger.info("程序被手动终止")
			break
		except Exception as e:
			logger.error(f"心跳发送过程中遇到异常: {e}")
			time.sleep(config["heartbeat_interval"])



